<template>
  <div
    :class="prefixCls"
    :style="swiperStyle"
    @mouseenter="mouseEnterHandle"
    @mouseleave="mouseLeaveHandle"
    @click="clickHandle"
  >
    <transition name="vbestui-swiper">
      <div :class="prefixCls+'-toggle'" v-show="isShowToggleIcon">
        <div :class="prefixCls+'-prefix'">
          <div class="vbestui-prefix-item vbestui-iconfont icon-hou" @click="preImgHandle">
            <i></i>
          </div>
        </div>
        <div :class="prefixCls+'-suffix'">
          <div class="vbestui-suffix-item vbestui-iconfont icon-qian" @click="sufImgHandle">
            <i></i>
          </div>
        </div>
      </div>
    </transition>
    <div :class="prefixCls+'-container'" :style="containerStyle" ref="imgContainer">
      <slot></slot>
    </div>
    <div :class="prefixCls+'-dots'" v-if="isShowDots">
      <ul>
        <li
          v-for="(n,index) in childLength"
          :key="index"
          :style="{background:n==currentIndex?dotsActiveColor:dotsBaseColor}"
          @click="dotsClickHandle(n)"
          @mouseover="dotsHoverHandle(n)"
          :class="[prefixCls+'-dots-item',n==currentIndex?prefixCls+'-dot-active':'',
          circleDots?prefixCls+'-dots-item-circle':'']"
        ></li>
      </ul>
    </div>
  </div>
</template>
<script>
import { oneOf } from "utils/index.js";
const prefixCls = "vbestui-swiper";
export default {
  name: "BSwiper",
  provide() {
    return {
      swiper: this,
    };
  },
  props: {
    value: {
      type: Number,
      default: 0,
    },
    width: {
      type: Number,
      default: 500,
    },
    height: {
      type: Number,
      default: 0,
    },
    toggleTime: {
      type: Number,
      default: 4000,
    },
    trigger: {
      validator(value) {
        return oneOf(value, ["click", "hover"]);
      },
      default: "click",
    },
    /**指示器位置 */
    dots: {
      validator(value) {
        return oneOf(value, ["inside", "outside", "none"]);
      },
      default: "inside",
    },
    /**指示器样式 */
    circleDots: {
      type: Boolean,
      default: false,
    },
    dotsBaseColor: {
      type: String,
      default: "#fff",
    },
    dotsActiveColor: {
      type: String,
      default: "green",
    },
    /**切换箭头显示时机 */
    arrow: {
      validator(value) {
        return oneOf(value, ["hover", "always", "never"]);
      },
      default: "hover",
    },
    easing: {
      validator(value) {
        return oneOf(value, [
          "linear",
          "ease",
          "ease-in",
          "ease-out",
          "ease-in-out",
        ]);
      },
      default: "ease",
    },
  },
  data() {
    return {
      isShowIcon: false,
      prefixCls: prefixCls,
      timer: null,
      childLength: 0,
      currentIndex: 1,
      contaiSty: {},
    };
  },
  computed: {
    swiperStyle() {
      return {
        width: `${this.width}px`,
        height:
          this.height != 0
            ? this.dots == "outside"
              ? `${this.height + 30}px`
              : `${this.height}px`
            : "",
      };
    },
    containerStyle() {
      return {
        width: `${this.width * (this.childLength + 2)}px`,
        height: this.dots == "outside" ? `calc(100% - 30px)` : "",
        transition : `all .6s ${this.easing}`
      };
    },
    isShowDots() {
      return this.childLength != 0 && this.dots != "none";
    },
    /**切换箭头显示时机 */
    isShowToggleIcon() {
      if (this.arrow == "always") {
        return true;
      }
      if (this.arrow == "never") {
        return false;
      }
      return this.isShowIcon;
    },
  },
  methods: {
    /**开始轮播 */
    beginSwiper() {
      this.timer = setInterval(() => {
        this.sufImgHandle();
      }, this.toggleTime);
    },
    /**点击轮播图图片 */
    clickHandle() {
      this.$emit("click", this.currentIndex);
    },
    /**处理指示器点击切换 */
    dotsClickHandle(n) {
      if (this.trigger != "click") return;
      this.currentIndex = n;
      this.setTransform(this.currentIndex);
      this.$emit("input", this.currentIndex);
      this.$emit("change", this.currentIndex - 1, this.currentIndex);
    },
    /**经过指示器切换图片 */
    dotsHoverHandle(n) {
      if (this.trigger != "hover") return;
      this.currentIndex = n;
      this.setTransform(this.currentIndex);
      this.$emit("input", this.currentIndex);
      this.$emit("change", this.currentIndex - 1, this.currentIndex);
    },
    /**点击icon图标切换图片 */
    preImgHandle() {
      this.currentIndex--;
      if (this.currentIndex < 0) this.currentIndex = this.childLength;
      this.setTransform(this.currentIndex);
      this.$emit("input", this.currentIndex);
      this.$emit("change", this.currentIndex - 1, this.currentIndex);
    },
    sufImgHandle() {
      this.currentIndex++;
      if (this.currentIndex > this.childLength + 1) this.currentIndex = 1;
      this.setTransform(this.currentIndex);
      this.$emit("input", this.currentIndex);
      this.$emit("change", this.currentIndex - 1, this.currentIndex);
    },
    mouseEnterHandle() {
      this.isShowIcon = true;
      clearInterval(this.timer);
    },
    mouseLeaveHandle() {
      this.isShowIcon = false;
      this.beginSwiper();
    },
    /**操作轮播图 */
    initChildsHandle() {
      const imgContainer = this.$refs.imgContainer;
      const childs = imgContainer.children;

      this.childLength = childs.length;
      if (this.childLength > 1) {
        /**不用$nextTick clone的子元素宽高不对
         * $nextTick().then()方式比$nextTick(()=>{})方式准确
         */
        this.$nextTick().then(() => {
          const cloneHeadDom = childs[0].cloneNode(true);
          const cloneFooterDom = childs[this.childLength - 1].cloneNode(true);
          imgContainer.appendChild(cloneHeadDom);
          imgContainer.insertBefore(cloneFooterDom, childs[0]);
          this.currentIndex = 1;
          this.contaiSty = imgContainer.style;
          this.setTransform(this.currentIndex);
        });
      }
    },
    setTransform(index, duration = 0.6) {
      if (index == this.childLength + 1) {
        duration = 0;
        index = 1;
        this.currentIndex = 1;
      } else if (index == 0) {
        duration = 0;
        index = 4;
        this.currentIndex = 4;
      }
      this.contaiSty.transform = `translate3d(${-index * this.width}px, 0, 0)`;
      this.contaiSty["-webkit-transform"] = `translate3d(${
        -index * this.width
      }px), 0, 0`;
      this.contaiSty["-ms-transform"] = `translate3d(${
        -index * this.width
      }px), 0, 0`;
      this.contaiSty.transition = `all ${duration}s ${this.easing}`;
    },
  },
  mounted() {
    this.$nextTick().then(() => {
      this.initChildsHandle();
      this.beginSwiper();
    });
  },
  watch: {
    toggleTime() {
      clearInterval(this.timer);
      this.beginSwiper();
    },
  },
};
</script>